home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / gdata / spreadsheet / text_db.pyc (.txt) < prev   
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  19.9 KB  |  496 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import StringIO
  5. import gdata
  6. import gdata.service as gdata
  7. import gdata.spreadsheet as gdata
  8. import gdata.spreadsheet.service as gdata
  9. import gdata.docs as gdata
  10. import gdata.docs.service as gdata
  11. __author__ = 'api.jscudder (Jeffrey Scudder)'
  12.  
  13. class Error(Exception):
  14.     pass
  15.  
  16.  
  17. class BadCredentials(Error):
  18.     pass
  19.  
  20.  
  21. class CaptchaRequired(Error):
  22.     pass
  23.  
  24.  
  25. class DatabaseClient(object):
  26.     '''Allows creation and finding of Google Spreadsheets databases.
  27.  
  28.   The DatabaseClient simplifies the process of creating and finding Google 
  29.   Spreadsheets and will talk to both the Google Spreadsheets API and the 
  30.   Google Documents List API. 
  31.   '''
  32.     
  33.     def __init__(self, username = None, password = None):
  34.         '''Constructor for a Database Client. 
  35.   
  36.     If the username and password are present, the constructor  will contact
  37.     the Google servers to authenticate.
  38.  
  39.     Args:
  40.       username: str (optional) Example: jo@example.com
  41.       password: str (optional)
  42.     '''
  43.         self._DatabaseClient__docs_client = gdata.docs.service.DocsService()
  44.         self._DatabaseClient__spreadsheets_client = gdata.spreadsheet.service.SpreadsheetsService()
  45.         self.SetCredentials(username, password)
  46.  
  47.     
  48.     def SetCredentials(self, username, password):
  49.         '''Attempts to log in to Google APIs using the provided credentials.
  50.  
  51.     If the username or password are None, the client will not request auth 
  52.     tokens.
  53.  
  54.     Args:
  55.       username: str (optional) Example: jo@example.com
  56.       password: str (optional)
  57.     '''
  58.         self._DatabaseClient__docs_client.email = username
  59.         self._DatabaseClient__docs_client.password = password
  60.         self._DatabaseClient__spreadsheets_client.email = username
  61.         self._DatabaseClient__spreadsheets_client.password = password
  62.         if username and password:
  63.             
  64.             try:
  65.                 self._DatabaseClient__docs_client.ProgrammaticLogin()
  66.                 self._DatabaseClient__spreadsheets_client.ProgrammaticLogin()
  67.             except gdata.service.CaptchaRequired:
  68.                 raise CaptchaRequired('Please visit https://www.google.com/accounts/DisplayUnlockCaptcha to unlock your account.')
  69.             except gdata.service.BadAuthentication:
  70.                 raise BadCredentials('Username or password incorrect.')
  71.             except:
  72.                 None<EXCEPTION MATCH>gdata.service.CaptchaRequired
  73.             
  74.  
  75.         None<EXCEPTION MATCH>gdata.service.CaptchaRequired
  76.  
  77.     
  78.     def CreateDatabase(self, name):
  79.         '''Creates a new Google Spreadsheet with the desired name.
  80.  
  81.     Args:
  82.       name: str The title for the spreadsheet.
  83.  
  84.     Returns:
  85.       A Database instance representing the new spreadsheet. 
  86.     '''
  87.         virtual_csv_file = StringIO.StringIO(',,,')
  88.         virtual_media_source = gdata.MediaSource(file_handle = virtual_csv_file, content_type = 'text/csv', content_length = 3)
  89.         db_entry = self._DatabaseClient__docs_client.UploadSpreadsheet(virtual_media_source, name)
  90.         return Database(spreadsheet_entry = db_entry, database_client = self)
  91.  
  92.     
  93.     def GetDatabases(self, spreadsheet_key = None, name = None):
  94.         """Finds spreadsheets which have the unique key or title.
  95.  
  96.     If querying on the spreadsheet_key there will be at most one result, but
  97.     searching by name could yield multiple results.
  98.  
  99.     Args:
  100.       spreadsheet_key: str The unique key for the spreadsheet, this 
  101.           usually in the the form 'pk23...We' or 'o23...423.12,,,3'.
  102.       name: str The title of the spreadsheets.
  103.  
  104.     Returns:
  105.       A list of Database objects representing the desired spreadsheets.
  106.     """
  107.         if spreadsheet_key:
  108.             db_entry = self._DatabaseClient__docs_client.GetDocumentListEntry('/feeds/documents/private/full/spreadsheet%3A' + spreadsheet_key)
  109.             return [
  110.                 Database(spreadsheet_entry = db_entry, database_client = self)]
  111.         title_query = gdata.docs.service.DocumentQuery()
  112.         title_query['title'] = name
  113.         db_feed = self._DatabaseClient__docs_client.QueryDocumentListFeed(title_query.ToUri())
  114.         matching_databases = []
  115.         for entry in db_feed.entry:
  116.             matching_databases.append(Database(spreadsheet_entry = entry, database_client = self))
  117.         
  118.         return matching_databases
  119.  
  120.     
  121.     def _GetDocsClient(self):
  122.         return self._DatabaseClient__docs_client
  123.  
  124.     
  125.     def _GetSpreadsheetsClient(self):
  126.         return self._DatabaseClient__spreadsheets_client
  127.  
  128.  
  129.  
  130. class Database(object):
  131.     '''Provides interface to find and create tables.
  132.  
  133.   The database represents a Google Spreadsheet.
  134.   '''
  135.     
  136.     def __init__(self, spreadsheet_entry = None, database_client = None):
  137.         """Constructor for a database object.
  138.  
  139.     Args:
  140.       spreadsheet_entry: gdata.docs.DocumentListEntry The 
  141.           Atom entry which represents the Google Spreadsheet. The
  142.           spreadsheet's key is extracted from the entry and stored as a 
  143.           member.
  144.       database_client: DatabaseClient A client which can talk to the
  145.           Google Spreadsheets servers to perform operations on worksheets
  146.           within this spreadsheet.
  147.     """
  148.         self.entry = spreadsheet_entry
  149.         if self.entry:
  150.             id_parts = spreadsheet_entry.id.text.split('/')
  151.             self.spreadsheet_key = id_parts[-1].replace('spreadsheet%3A', '')
  152.         
  153.         self.client = database_client
  154.  
  155.     
  156.     def CreateTable(self, name, fields = None):
  157.         """Add a new worksheet to this spreadsheet and fill in column names.
  158.  
  159.     Args:
  160.       name: str The title of the new worksheet.
  161.       fields: list of strings The column names which are placed in the
  162.           first row of this worksheet. These names are converted into XML
  163.           tags by the server. To avoid changes during the translation
  164.           process I recommend using all lowercase alphabetic names. For
  165.           example ['somelongname', 'theothername']
  166.  
  167.     Returns:
  168.       Table representing the newly created worksheet.
  169.     """
  170.         worksheet = self.client._GetSpreadsheetsClient().AddWorksheet(title = name, row_count = 1, col_count = len(fields), key = self.spreadsheet_key)
  171.         return Table(name = name, worksheet_entry = worksheet, database_client = self.client, spreadsheet_key = self.spreadsheet_key, fields = fields)
  172.  
  173.     
  174.     def GetTables(self, worksheet_id = None, name = None):
  175.         """Searches for a worksheet with the specified ID or name.
  176.  
  177.     The list of results should have one table at most, or no results
  178.     if the id or name were not found.
  179.  
  180.     Args:
  181.       worksheet_id: str The ID of the worksheet, example: 'od6'
  182.       name: str The title of the worksheet.
  183.  
  184.     Returns:
  185.       A list of length 0 or 1 containing the desired Table. A list is returned
  186.       to make this method feel like GetDatabases and GetRecords.
  187.     """
  188.         if worksheet_id:
  189.             worksheet_entry = self.client._GetSpreadsheetsClient().GetWorksheetsFeed(self.spreadsheet_key, wksht_id = worksheet_id)
  190.             return [
  191.                 Table(name = worksheet_entry.title.text, worksheet_entry = worksheet_entry, database_client = self.client, spreadsheet_key = self.spreadsheet_key)]
  192.         matching_tables = []
  193.         query = None
  194.         if name:
  195.             query = gdata.spreadsheet.service.DocumentQuery()
  196.             query.title = name
  197.         
  198.         worksheet_feed = self.client._GetSpreadsheetsClient().GetWorksheetsFeed(self.spreadsheet_key, query = query)
  199.         for entry in worksheet_feed.entry:
  200.             matching_tables.append(Table(name = entry.title.text, worksheet_entry = entry, database_client = self.client, spreadsheet_key = self.spreadsheet_key))
  201.         
  202.         return matching_tables
  203.  
  204.     
  205.     def Delete(self):
  206.         '''Deletes the entire database spreadsheet from Google Spreadsheets.'''
  207.         entry = self.client._GetDocsClient().Get('http://docs.google.com/feeds/documents/private/full/spreadsheet%3A' + self.spreadsheet_key)
  208.         self.client._GetDocsClient().Delete(entry.GetEditLink().href)
  209.  
  210.  
  211.  
  212. class Table(object):
  213.     
  214.     def __init__(self, name = None, worksheet_entry = None, database_client = None, spreadsheet_key = None, fields = None):
  215.         self.name = name
  216.         self.entry = worksheet_entry
  217.         id_parts = worksheet_entry.id.text.split('/')
  218.         self.worksheet_id = id_parts[-1]
  219.         self.spreadsheet_key = spreadsheet_key
  220.         self.client = database_client
  221.         if not fields:
  222.             pass
  223.         self.fields = []
  224.         if fields:
  225.             self.SetFields(fields)
  226.         
  227.  
  228.     
  229.     def LookupFields(self):
  230.         """Queries to find the column names in the first row of the worksheet.
  231.     
  232.     Useful when you have retrieved the table from the server and you don't 
  233.     know the column names.
  234.     """
  235.         if self.entry:
  236.             first_row_contents = []
  237.             query = gdata.spreadsheet.service.CellQuery()
  238.             query.max_row = '1'
  239.             query.min_row = '1'
  240.             feed = self.client._GetSpreadsheetsClient().GetCellsFeed(self.spreadsheet_key, wksht_id = self.worksheet_id, query = query)
  241.             for entry in feed.entry:
  242.                 first_row_contents.append(entry.content.text)
  243.             
  244.             next_link = feed.GetNextLink()
  245.             while next_link:
  246.                 feed = self.client._GetSpreadsheetsClient().Get(next_link.href, converter = gdata.spreadsheet.SpreadsheetsCellsFeedFromString)
  247.                 for entry in feed.entry:
  248.                     first_row_contents.append(entry.content.text)
  249.                 
  250.                 next_link = feed.GetNextLink()
  251.             self.fields = ConvertStringsToColumnHeaders(first_row_contents)
  252.         
  253.  
  254.     
  255.     def SetFields(self, fields):
  256.         """Changes the contents of the cells in the first row of this worksheet.
  257.  
  258.     Args:
  259.       fields: list of strings The names in the list comprise the
  260.           first row of the worksheet. These names are converted into XML
  261.           tags by the server. To avoid changes during the translation
  262.           process I recommend using all lowercase alphabetic names. For
  263.           example ['somelongname', 'theothername']
  264.     """
  265.         self.fields = fields
  266.         i = 0
  267.         for column_name in fields:
  268.             i = i + 1
  269.             self.client._GetSpreadsheetsClient().UpdateCell(1, i, column_name, self.spreadsheet_key, self.worksheet_id)
  270.         
  271.  
  272.     
  273.     def Delete(self):
  274.         '''Deletes this worksheet from the spreadsheet.'''
  275.         worksheet = self.client._GetSpreadsheetsClient().GetWorksheetsFeed(self.spreadsheet_key, wksht_id = self.worksheet_id)
  276.         self.client._GetSpreadsheetsClient().DeleteWorksheet(worksheet_entry = worksheet)
  277.  
  278.     
  279.     def AddRecord(self, data):
  280.         '''Adds a new row to this worksheet.
  281.  
  282.     Args:
  283.       data: dict of strings Mapping of string values to column names. 
  284.  
  285.     Returns:
  286.       Record which represents this row of the spreadsheet.
  287.     '''
  288.         new_row = self.client._GetSpreadsheetsClient().InsertRow(data, self.spreadsheet_key, wksht_id = self.worksheet_id)
  289.         return Record(content = data, row_entry = new_row, spreadsheet_key = self.spreadsheet_key, worksheet_id = self.worksheet_id, database_client = self.client)
  290.  
  291.     
  292.     def GetRecord(self, row_id = None, row_number = None):
  293.         '''Gets a single record from the worksheet based on row ID or number.
  294.     
  295.     Args:
  296.       row_id: The ID for the individual row.
  297.       row_number: str or int The position of the desired row. Numbering 
  298.           begins at 1, which refers to the second row in the worksheet since
  299.           the first row is used for column names.
  300.  
  301.     Returns:
  302.       Record for the desired row.
  303.     '''
  304.         if row_id:
  305.             row_entry = self.client._GetSpreadsheetsClient().GetListFeed(self.spreadsheet_key, wksht_id = self.worksheet_id, row_id = row_id)
  306.             return Record(content = None, row_entry = row_entry, spreadsheet_key = self.spreadsheet_key, worksheet_id = self.worksheet_id, database_client = self.client)
  307.         row_query = gdata.spreadsheet.service.ListQuery()
  308.         row_query.start_index = str(row_number)
  309.         row_query.max_results = '1'
  310.         row_feed = self.client._GetSpreadsheetsClient().GetListFeed(self.spreadsheet_key, wksht_id = self.worksheet_id, query = row_query)
  311.         if len(row_feed.entry) >= 1:
  312.             return Record(content = None, row_entry = row_feed.entry[0], spreadsheet_key = self.spreadsheet_key, worksheet_id = self.worksheet_id, database_client = self.client)
  313.         return None
  314.  
  315.     
  316.     def GetRecords(self, start_row, end_row):
  317.         '''Gets all rows between the start and end row numbers inclusive.
  318.  
  319.     Args:
  320.       start_row: str or int
  321.       end_row: str or int
  322.  
  323.     Returns:
  324.       RecordResultSet for the desired rows.
  325.     '''
  326.         start_row = int(start_row)
  327.         end_row = int(end_row)
  328.         max_rows = (end_row - start_row) + 1
  329.         row_query = gdata.spreadsheet.service.ListQuery()
  330.         row_query.start_index = str(start_row)
  331.         row_query.max_results = str(max_rows)
  332.         rows_feed = self.client._GetSpreadsheetsClient().GetListFeed(self.spreadsheet_key, wksht_id = self.worksheet_id, query = row_query)
  333.         return RecordResultSet(rows_feed, self.client, self.spreadsheet_key, self.worksheet_id)
  334.  
  335.     
  336.     def FindRecords(self, query_string):
  337.         """Performs a query against the worksheet to find rows which match.
  338.  
  339.     For details on query string syntax see the section on sq under
  340.     http://code.google.com/apis/spreadsheets/reference.html#list_Parameters
  341.  
  342.     Args:
  343.       query_string: str Examples: 'name == john' to find all rows with john
  344.           in the name column, '(cost < 19.50 and name != toy) or cost > 500'
  345.  
  346.     Returns:
  347.       RecordResultSet with the first group of matches.
  348.     """
  349.         row_query = gdata.spreadsheet.service.ListQuery()
  350.         row_query.sq = query_string
  351.         matching_feed = self.client._GetSpreadsheetsClient().GetListFeed(self.spreadsheet_key, wksht_id = self.worksheet_id, query = row_query)
  352.         return RecordResultSet(matching_feed, self.client, self.spreadsheet_key, self.worksheet_id)
  353.  
  354.  
  355.  
  356. class RecordResultSet(list):
  357.     '''A collection of rows which allows fetching of the next set of results.
  358.  
  359.   The server may not send all rows in the requested range because there are
  360.   too many. Using this result set you can access the first set of results
  361.   as if it is a list, then get the next batch (if there are more results) by
  362.   calling GetNext().
  363.   '''
  364.     
  365.     def __init__(self, feed, client, spreadsheet_key, worksheet_id):
  366.         self.client = client
  367.         self.spreadsheet_key = spreadsheet_key
  368.         self.worksheet_id = worksheet_id
  369.         self.feed = feed
  370.         list(self)
  371.         for entry in self.feed.entry:
  372.             self.append(Record(content = None, row_entry = entry, spreadsheet_key = spreadsheet_key, worksheet_id = worksheet_id, database_client = client))
  373.         
  374.  
  375.     
  376.     def GetNext(self):
  377.         '''Fetches the next batch of rows in the result set.
  378.  
  379.     Returns:
  380.       A new RecordResultSet.
  381.     '''
  382.         next_link = self.feed.GetNextLink()
  383.         if next_link and next_link.href:
  384.             new_feed = self.client._GetSpreadsheetsClient().Get(next_link.href, converter = gdata.spreadsheet.SpreadsheetsListFeedFromString)
  385.             return RecordResultSet(new_feed, self.client, self.spreadsheet_key, self.worksheet_id)
  386.  
  387.  
  388.  
  389. class Record(object):
  390.     '''Represents one row in a worksheet and provides a dictionary of values.
  391.  
  392.   Attributes:
  393.     custom: dict Represents the contents of the row with cell values mapped
  394.         to column headers.
  395.   '''
  396.     
  397.     def __init__(self, content = None, row_entry = None, spreadsheet_key = None, worksheet_id = None, database_client = None):
  398.         '''Constructor for a record.
  399.     
  400.     Args:
  401.       content: dict of strings Mapping of string values to column names.
  402.       row_entry: gdata.spreadsheet.SpreadsheetsList The Atom entry 
  403.           representing this row in the worksheet.
  404.       spreadsheet_key: str The ID of the spreadsheet in which this row 
  405.           belongs.
  406.       worksheet_id: str The ID of the worksheet in which this row belongs.
  407.       database_client: DatabaseClient The client which can be used to talk
  408.           the Google Spreadsheets server to edit this row.
  409.     '''
  410.         self.entry = row_entry
  411.         self.spreadsheet_key = spreadsheet_key
  412.         self.worksheet_id = worksheet_id
  413.         if row_entry:
  414.             self.row_id = row_entry.id.text.split('/')[-1]
  415.         else:
  416.             self.row_id = None
  417.         self.client = database_client
  418.         if not content:
  419.             pass
  420.         self.content = { }
  421.         if not content:
  422.             self.ExtractContentFromEntry(row_entry)
  423.         
  424.  
  425.     
  426.     def ExtractContentFromEntry(self, entry):
  427.         """Populates the content and row_id based on content of the entry.
  428.  
  429.     This method is used in the Record's contructor.
  430.  
  431.     Args:
  432.       entry: gdata.spreadsheet.SpreadsheetsList The Atom entry 
  433.           representing this row in the worksheet.
  434.     """
  435.         self.content = { }
  436.         if entry:
  437.             self.row_id = entry.id.text.split('/')[-1]
  438.             for label, custom in entry.custom.iteritems():
  439.                 self.content[label] = custom.text
  440.             
  441.         
  442.  
  443.     
  444.     def Push(self):
  445.         '''Send the content of the record to spreadsheets to edit the row.
  446.  
  447.     All items in the content dictionary will be sent. Items which have been
  448.     removed from the content may remain in the row. The content member
  449.     of the record will not be modified so additional fields in the row
  450.     might be absent from this local copy.
  451.     '''
  452.         self.entry = self.client._GetSpreadsheetsClient().UpdateRow(self.entry, self.content)
  453.  
  454.     
  455.     def Pull(self):
  456.         '''Query Google Spreadsheets to get the latest data from the server.
  457.  
  458.     Fetches the entry for this row and repopulates the content dictionary 
  459.     with the data found in the row.
  460.     '''
  461.         if self.row_id:
  462.             self.entry = self.client._GetSpreadsheetsClient().GetListFeed(self.spreadsheet_key, wksht_id = self.worksheet_id, row_id = self.row_id)
  463.         
  464.         self.ExtractContentFromEntry(self.entry)
  465.  
  466.     
  467.     def Delete(self):
  468.         self.client._GetSpreadsheetsClient().DeleteRow(self.entry)
  469.  
  470.  
  471.  
  472. def ConvertStringsToColumnHeaders(proposed_headers):
  473.     '''Converts a list of strings to column names which spreadsheets accepts.
  474.  
  475.   When setting values in a record, the keys which represent column names must
  476.   fit certain rules. They are all lower case, contain no spaces or special
  477.   characters. If two columns have the same name after being sanitized, the 
  478.   columns further to the right have _2, _3 _4, etc. appended to them.
  479.  
  480.   If there are column names which consist of all special characters, or if
  481.   the column header is blank, an obfuscated value will be used for a column
  482.   name. This method does not handle blank column names or column names with
  483.   only special characters.
  484.   '''
  485.     headers = []
  486.     for input_string in proposed_headers:
  487.         sanitized = input_string.lower().replace('_', '').replace(':', '').replace(' ', '')
  488.         header_count = headers.count(sanitized)
  489.         if header_count > 0:
  490.             headers.append('%s_%i' % (sanitized, header_count + 1))
  491.             continue
  492.         headers.append(sanitized)
  493.     
  494.     return headers
  495.  
  496.